package com.hyb.algorithm.data.struct.tree;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: huyanbing
 * @Date: 2021/8/11 3:11 下午
 * <p>
 * 恢复二叉搜索树
 * 给你二叉搜索树的根节点 root ，该树中的两个节点被错误地交换。请在不改变其结构的情况下，恢复这棵树。
 * <p>
 * 进阶：使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗？
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/recover-binary-search-tree
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class RecoverBinarySearchTree {


    public static void main(String[] args) {


        /**
         * 输入：root = [3,1,4,null,null,2]
         * 输出：[2,1,4,null,null,3]
         * 解释：2 不能在 3 的右子树中，因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。
         *
         *
         *
         * 输入：root = [1,3,null,null,2]
         * 输出：[3,1,null,null,2]
         * 解释：3 不能是 1 左孩子，因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
         */
        RecoverBinarySearchTree binarySearchTree=new RecoverBinarySearchTree();

        TreeNode root=new TreeNode(3);
        root.left=new TreeNode(1);
        root.right=new TreeNode(4);

        binarySearchTree.recoverTree(root);


    }


    public void recoverTree(TreeNode root) {

        ArrayList<TreeNode> list = new ArrayList<>();

        inOrder(root, list);

        TreeNode a = null;
        TreeNode b = null;

        // 只有 两个 错序的节点
        //假设有一个递增序列 a=[1,2,3,4,5,6,7]
        // 如果我们交换两个不相邻的数字，例如 2 和 6，原序列变成了 a=[1,6,3,4,5,2,7]
        for (int i = 1; i < list.size(); i++) {
            if (list.get(i).val < list.get(i - 1).val) {
                if (a == null) {
                    a = list.get(i-1);
                    b = list.get(i);
                } else {
                    b = list.get(i);
                    break;
                }
            }
        }

        int temp=a.val;
        a.val=b.val;
        b.val=temp;

    }


    /**
     * 利用中序排序的特点  从小到大排序
     *
     * @param node
     * @param list
     */
    public void inOrder(TreeNode node, ArrayList<TreeNode> list) {

        if (node == null) {
            return;
        }

        inOrder(node.left, list);
        list.add(node);
        inOrder(node.right, list);
    }


}
